/**
  ******************************************************************************
  * @file     main.c
  * @author   MCD Application Team
  * @version  V1.0.0
  * @date     03/01/2010
  * @brief    Main program body
  ******************************************************************************
  * @copy
  *
  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
  * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
  * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
  *
  * <h2><center>&copy; COPYRIGHT 2010 STMicroelectronics</center></h2>
  */





/* Includes ------------------------------------------------------------------*/
#include "Config.h"
#include "w25qxx.h"
#include "sys.h" 

iapfun jump2app; 
uint8 Cope_SPIFlash_To_StmFlash(uint32 AddrMtd_Start);
/* 函数定义  */
void RCC_Configuration(void);                   // 时钟初始化
void NVIC_Configuration(void);                  // 中断优先级初始化
void OS_CPU_SysTick_Init(void);                 // 系统节拍器初始化
void Delay_nms(u16 wCount);                     /* 毫秒级延时函数 32M晶振*/
void Delay_nus(u16 wCount);                     /* 微秒级延时函数 32M晶振*/ 
void MCU_Reset(void);				/* MCU复位处理*/
void User_Data_Init(void);                      /* 用户数据初始化 */                  
void Check_IAP_CMD(void);                       /* IAP检测 */
void QuitBootLoad(void);                        /* 退出启动程序，进入应用程序 */
uint16 calcrc(uint8 *ptr, uint8 count);         //计算CRC16
void write_one_page(void);                      /* 写一页FLASH  */
void Get_XMODEM_Data(uint8 *p);
uint16 Get_UART_Rec_Count(void);                /* 获取串口接收数据长度 */
void Cope_EEPROM_To_Flash(void);                /* 升级程序 */

uint8 Cope_SPIFlash_To_StmFlash(uint32 AddrMtd_Start);
void Cope_StmFlash_To_SPIFlash(uint32 AddrMtd_Start);

void SPIFLASH_CheckRom_Status(void);

/* 调试显示常量定义 */
static const char iDebug_Disp0_1[] = "STM32 IAP Start!\n";
static const char iDebug_Disp0_2[] = "Wait First XMODEM Data!\n";
static const char iDebug_Disp0_3[] = "Get Datas OK!\n";
static const char iDebug_Disp0_4[] = "Cancel XMODEM\n";
static const char iDebug_Disp0_5[] = "Over Data!\n";
static const char iDebug_Disp0_6[] = "STM32 Start Updata!\n";
static const char iDebug_Disp0_7[] = "STM32 Updata OK!\n";




struct str_XMODEM
{
    unsigned char SOH;						//起始字节
    unsigned char BlockNo;					//数据块编号
    unsigned char nBlockNo;					//数据块编号反码
    unsigned char Xdata[128];				        //数据128字节
    unsigned char CRC16hi;					//CRC16校验数据高位
    unsigned char CRC16lo;					//CRC16校验数据低位
};		


struct str_XMODEM strXMODEM;

/* 全局变量定义  */
vu8 iEvent_Flag = 0;			        /* 系统标志位 */
vu8 iEvent_Flag2 = 0;			        /* 系统标志位 */
vu8 iEvent_Flag3 = 0;			        /* 系统标志位 */
vu8 iEvent_Flag4 = 0;			        /* 系统标志位 */
vu8 iIAP_Status = 0;                            // IAP状态机
vu8 iTimer_UART_Rec = 0;                        // 接收间隔时间       

/* 静态变量定义 */
static u8 iTemp_Buf[4];
static u32 lFlashAddress = 0;
static u16 wBlockCount = 0;
static u16 wCount = 0;
static u16 wCRC = 0;
static u16 wCRC_Temp = 0;
static u8 ReceiveDataBuf[PAGE_SIZE];
static u32 lUpdata_Length = 0;

void Delay_nms(u16 wCount)
{
  u32 i = (u32)wCount * 5333*3;
  for(; i != 0; i--);
}

#define	GPIO_Pin_LED1	GPIO_Pin_10
#define	GPIO_Pin_LED2	GPIO_Pin_15
#define	GPIO_Pin_LIGHT	GPIO_Pin_11

#define	P_Out_LED1	 	PCout(10)
#define	P_Out_LED2	 	PAout(15)
#define	P_Out_LIGHT	 	PCout(11)

#define	GPIO_Pin_Motor1_P		GPIO_Pin_9
#define	GPIO_Pin_Motor1_N		GPIO_Pin_8

#define	GPIO_Pin_Motor2_P		GPIO_Pin_4
#define	GPIO_Pin_Motor2_N		GPIO_Pin_3


#define	P_Out_Motor1_P	 		PBout(9)
#define	P_Out_Motor1_N	 		PBout(8)

#define	P_Out_Motor2_P	 		PBout(4)
#define	P_Out_Motor2_N	 		PBout(3)

void MOTOR_Init(void)
{				
	GPIO_InitTypeDef  GPIO_InitStructure; 
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE); //原来的初始化代码没有打开时钟 
	
	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable , ENABLE);
	
	GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_Motor1_P|GPIO_Pin_Motor1_N|GPIO_Pin_Motor2_P|GPIO_Pin_Motor2_N; 
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;     
	GPIO_Init(GPIOB, &GPIO_InitStructure); 	
		
	P_Out_Motor1_P = 0;
	P_Out_Motor1_N = 1;
	
	P_Out_Motor2_P = 0;
	P_Out_Motor2_N = 1;
	
}

void LED_Init(void)
{			

	
	GPIO_InitTypeDef  GPIO_InitStructure; 
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC |RCC_APB2Periph_AFIO, ENABLE); //原来的初始化代码没有打开时钟 
	
	

	
	GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_LIGHT; 
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;     
	GPIO_Init(GPIOC, &GPIO_InitStructure);	
	

	P_Out_LIGHT = 1;
}

/* 主函数 */
int main(void)
{  
	uint8 i,j;
//	LED_Init();
	MOTOR_Init();
	Delay_nms(500);
	//SystemInit();                           // 时钟初始化

	RCC_Configuration();                    // 时钟初始化
	NVIC_Configuration();                   // 中断向量配置初始化 
	MOTOR_Init();
	CLI();                                  // Disable Interrupts
	uart_init(9600);                           // 串口0初始化（USART1）
	//  uart1_Init();                           // 串口1初始化（USART2）
	//  uart2_Init();                           // 串口2初始化（USART3）
	//  Timer1_Init();                           // 定时器1初始化
	//  Timer2_Init();  
	//  LED_Init();
	TIM3_Int_Init(199,1599);
	User_Data_Init();                       // 用户数据初始化     
	W25QXX_Init();

	//  // 独立看门狗应用
	//  IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); //使能写入PR和RLR
	//  IWDG_SetPrescaler(IWDG_Prescaler_128);        //写入PR预分频值
	//  IWDG_SetReload(0x8ff);                        //写入RLR  看门狗时间6.5536秒，定时中断每1秒喂狗一次
	//  IWDG_Enable();                                //KR写入0xCCCC
	//  
	//  printf(iDebug_Disp0_1));

	iEvent_Flag |= EVENT_SYS_IWDG;
	printf("XRJ STM32F103 IAP v2.0 Start\n");
//	Cope_SPIFlash_To_StmFlash();
//	Cope_StmFlash_To_SPIFlash();
	
	SPIFLASH_CheckRom_Status();
	Check_IAP_CMD();                        // IAP检测－－跳转到应用程序区，或进入IAP更新区域

	printf(iDebug_Disp0_1);

	SEI();                                  // Enable Interrupts
	while (1)
	{ 
		if(iEvent_Flag2 & EVENT_IAP_DATA_OK)
		{
			STM32_EEPROM_Read(EE_SYS_IAP_LENGTH,(uint8 *)iTemp_Buf,4);
			lUpdata_Length = (uint32)iTemp_Buf[0]*0x1000000;
			lUpdata_Length += (uint32)iTemp_Buf[1]*0x10000;
			lUpdata_Length += (uint32)iTemp_Buf[2]*0x100;
			lUpdata_Length += (uint32)iTemp_Buf[3];

			printf("%x %x %x %x",iTemp_Buf[0],iTemp_Buf[1],iTemp_Buf[2],iTemp_Buf[3]);

			printf(iDebug_Disp0_6);

			Cope_EEPROM_To_Flash();       // 升级程序

			printf(iDebug_Disp0_7);
			QuitBootLoad();               // 跳转到应用区
		// 准备接收数据：
		}
		else
		{
			lFlashAddress = 0;
			wBlockCount = 0x01;	
			wCount = 0;
			// 接收数据
			while(iIAP_Status != ST_OK)
			{
			// XMODEM未启动
				if(iIAP_Status == ST_WAIT_START)
				{
					if(iEvent_Flag & EVENT_TIMER_SEC_FLAG)
					{
					  iEvent_Flag &= (uint8)(~EVENT_TIMER_SEC_FLAG);
					  printf("%c",XMODEM_WAIT_CHAR);	                //发送请求XMODEM_WAIT_CHAR
					}       
				}
				//接收133字节数据
				i = Get_UART_Rec_Count();
				if(i >= 133)
				{
					iTimer_UART_Rec = 0;                        // 接收间隔时间  
					Get_XMODEM_Data((uint8 *)&strXMODEM.SOH);
					//分析数据包的第一个数据 SOH/EOT/CAN

					switch(strXMODEM.SOH)
					{
						case XMODEM_SOH:				        //收到开始符SOH
							iIAP_Status = ST_BLOCK_OK;
							break;
						default:						//起始字节错误
							printf("%c",XMODEM_NAK);				//要求重发当前数据块
							iIAP_Status = ST_BLOCK_FAIL;
							break;
					}
					//接收133字节OK，且起始字节正确
					if(iIAP_Status == ST_BLOCK_OK)			
					{
						//核对数据块编号/反码判断
						if(((uint8)wBlockCount != (uint8)strXMODEM.BlockNo))// || ((uint8)wBlockCount != (uint8)(~strXMODEM.nBlockNo)))        
						{
							printf("c %x %x %x %c",strXMODEM.BlockNo,strXMODEM.nBlockNo,wBlockCount,XMODEM_NAK);//数据块编号错误，要求重发当前数据块		
						}
						else
						{
							// 数据校验判断
							wCRC = (uint16)strXMODEM.CRC16hi * 256;            
							wCRC += strXMODEM.CRC16lo;
							//AVR的16位整数是低位在先，XMODEM的CRC16是高位在先
							wCRC_Temp = calcrc(&strXMODEM.Xdata[0],128);
							if(wCRC_Temp != wCRC)
							{
								printf("%c",XMODEM_NAK);        		//CRC错误，要求重发当前数据块
							}
							else
							{
								//正确接收128个字节数据，刚好是STM32的1/8页（1页＝1K）
								wCount++;
								if(wCount < (PAGE_SIZE/128))
								{                             
									for(j=0; j<128; j++)
									{
										ReceiveDataBuf[(wCount-1)*128+j] = strXMODEM.Xdata[j];
									}
									printf("%c",XMODEM_ACK);        		//回应已正确收到一个数据块
									wBlockCount++;                 		//数据块累计加1 
								// 接收1页数据
								}
								else
								{    
									for(j=0;j<128;j++)
									{
										ReceiveDataBuf[(wCount-1)*128+j] = strXMODEM.Xdata[j];
									}
									
									wCount = 0;
									if (lFlashAddress < (MCUCodeMaxWidth-PAGE_SIZE))
									{									    
										write_one_page();           	        //将收到数据写入一页Flash中
										lFlashAddress += PAGE_SIZE; 	        //Flash页加1
									}
									else
									{
										printf("%c%c%c",XMODEM_CAN,XMODEM_CAN,XMODEM_CAN);     			//程序已满，取消传送
										iIAP_Status = ST_OK;
										printf(iDebug_Disp0_5);
										break;
									}
									printf("%c",XMODEM_ACK);        			//回应已正确收到一个数据块
									wBlockCount++;                 		//数据块累计加1
								}
							}// 校验判断
						}// 编号判断
					}// 数据长度、起始字节判断 
				}//接收133字节数据
				else
				{
					if(iTimer_UART_Rec >= 10)
					{    // 接收间隔时间为1秒
						iTimer_UART_Rec = 0;
						if(i > 0)
						{
							strXMODEM.SOH = uart0.r_buf[uart0.r_out];
							uart0.r_out = uart0.r_in;   
							switch(strXMODEM.SOH)
							{
								case XMODEM_EOT:				        //收到结束符EOT
									if(wCount != 0)
									{                                // 尾数处理
										write_one_page();           	                //将收到数据写入一页Flash中 
									}	
									printf("%c",XMODEM_ACK);			        //通知PC机全部收到
									iIAP_Status = ST_OK;

									iTemp_Buf[0] = 0x88;
									iTemp_Buf[1] = 0x22;
									STM32_EEPROM_Write(EE_SYS_IAP_CMD,(uint8 *)iTemp_Buf,2,0);
									lUpdata_Length = (uint32)(wBlockCount-1) * 128;
									iTemp_Buf[0] = (uint8)(lUpdata_Length >> 24);
									iTemp_Buf[1] = (uint8)(lUpdata_Length >> 16);
									iTemp_Buf[2] = (uint8)(lUpdata_Length >> 8);
									iTemp_Buf[3] = (uint8)(lUpdata_Length);
									STM32_EEPROM_Write(EE_SYS_IAP_LENGTH,(uint8 *)iTemp_Buf,4,0);
									printf(iDebug_Disp0_3);
									MCU_Reset();                                    // 直接重启指令，允许程序更新
									break;
								case XMODEM_CAN:					//收到取消符CAN
									printf("%c",XMODEM_ACK);				//回应PC机
									iIAP_Status = ST_OK;
									printf(iDebug_Disp0_4);
									break;
								default:						//起始字节错误
									printf("%c",XMODEM_NAK);				//要求重发当前数据块
									iIAP_Status = ST_BLOCK_FAIL;
									break;
							}   
						}
					}
				}
			}// 接收数据
		}// 数据已接收判断  */
	}
  
}
/* 时钟初始化 */
void RCC_Configuration(void)          
{
    RCC_DeInit();

    /* Enable HSE */
    RCC_HSEConfig(RCC_HSE_ON);

    /* Wait till HSE is ready */

    if(RCC_WaitForHSEStartUp())
    {
        /* Enable Prefetch Buffer */
        FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

        /* Flash 2 wait state */
        FLASH_SetLatency(FLASH_Latency_2);
        /* Enable Prefetch Buffer */
				FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

        /* HCLK = SYSCLK */
        RCC_HCLKConfig(RCC_SYSCLK_Div1); 
  
        /* PCLK2 = HCLK */
        RCC_PCLK2Config(RCC_HCLK_Div1); 
 
        /* PCLK1 = HCLK/2 */
        RCC_PCLK1Config(RCC_HCLK_Div2);
 
        /* PLLCLK = 8MHz * 9 = 72 MHz */
        RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_4);   //RCC_PLLMul_9
 
        /* Enable PLL */ 
        RCC_PLLCmd(ENABLE);
 
        /* Wait till PLL is ready */
        while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
        {
        }
 
        /* Select PLL as system clock source */
        RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
 
        /* Wait till PLL is used as system clock source */
        while(RCC_GetSYSCLKSource() != 0x08)
        {
        }
    }
    SystemCoreClock = HSE_Value * 4;
    
    
 //   RCC_SYSCLKConfig(RCC_SYSCLKSource_HSE);/*设置系统时钟（SYSCLK）选择HSE作为系统时钟*/
 //   while(RCC_GetSYSCLKSource() != 0x04)
                                        /*等待成功用作于系统时钟的时钟源返回用作系统时钟的时钟源
                                          0x00：HSI作为系统时钟
                                          0x04：HSE作为系统时钟
                                          0x08：PLL作为系统时钟*/
 /*   {
    }
    SystemCoreClock = HSE_Value;*/

}
/*中断向量初始化*/
void NVIC_Configuration(void)
{

  #ifdef  VECT_TAB_RAM
    /* Set the Vector Table base location at 0x20000000 */
    NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
  #else  /* VECT_TAB_FLASH  */
    /* Set the Vector Table base location at 0x08000000 */
    NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
  #endif
  
  /* Configure the Priority Group to 2 bits */
  //最高2位用于指定抢占式优先级(0~3)，最低2位用于指定响应优先级(0~3)
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

}
/*******************************************************************************
* Function Name  : OS_CPU_SysTick_Config
* Description    : Configures SysTick
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
/* SysTick设置 *
void OS_CPU_SysTick_Init(void)
{
  // Setup SysTick Timer for 10 msec interrupts  //
  if (SysTick_Config(SystemCoreClock / OS_TICKS_PER_SEC))
  { 
      while (1);
  }
}*/

/*MCU复位处理*/
void MCU_Reset(void)
{
      
  iEvent_Flag = 0;
  iEvent_Flag2 = 0;
  iEvent_Flag3 = 0;
  iEvent_Flag4 = 0;
  
  __disable_fault_irq();      // STM32 软复位  
  NVIC_SystemReset();
}
///*毫秒级延时函数 32M晶振*/
//void Delay_nms(u16 wCount)
//{
//  u32 i = (u32)wCount * 5333;
//  for(; i != 0; i--);
//}
///*微秒级延时函数 32M晶振*/
//void Delay_nus(u16 wCount)
//{
//  u32 i = (uint32)wCount * 50 / 10;
//  for(; i != 0; i--);
//}

/* 用户数据初始化 */
void User_Data_Init(void)
{

  iEvent_Flag = 0;
  iEvent_Flag2 = 0;
  iEvent_Flag3 = 0;
  iEvent_Flag4 = 0;
  iEvent_Flag3 |= EVENT_TEST_DISP_EN;     // 调试使能
}
/* IAP检测 */
void Check_IAP_CMD(void)
{
  STM32_EEPROM_Read(EE_SYS_IAP_CMD,(uint8 *)iTemp_Buf,2);
  printf("IAP-%x %x\n",iTemp_Buf[0],iTemp_Buf[1]);
  	
  if((iTemp_Buf[0] == 0xAA) && (iTemp_Buf[1] == 0x55)){           // 升级成功
    QuitBootLoad();     
  }else if((iTemp_Buf[0] == 0x88) && (iTemp_Buf[1] == 0x11)){     // 数据已刷新,等待升级指令  
    QuitBootLoad();   
  }else if((iTemp_Buf[0] == 0x88) && (iTemp_Buf[1] == 0x22)){     // 升级指令，更新代码  
		printf(iDebug_Disp0_3);
    iEvent_Flag2 |= EVENT_IAP_DATA_OK;
  }else{                                                          // 程序不存在，需要数据刷新
    iEvent_Flag2 &= (uint8)(~EVENT_IAP_DATA_OK);
    iIAP_Status = ST_WAIT_START;                                 // 等待接收第一包数据
    printf(iDebug_Disp0_2);
  }
  
}
/* 获取串口接收数据长度 */
uint16 Get_UART_Rec_Count(void)
{
  uint16 wLen_Tmp = 0;

  if(uart0.r_in > uart0.r_out){
    wLen_Tmp = uart0.r_in - uart0.r_out; 
  }else if(uart0.r_in < uart0.r_out){
    wLen_Tmp = Debug_r_buf_len - uart0.r_out + uart0.r_in;
  }
  
  return wLen_Tmp;
}
void Get_XMODEM_Data(uint8 *p)
{
  uint8 i;
  for(i=0; i<133; i++){
    *(p+i) = uart0.r_buf[uart0.r_out];
//    uart0_puthex(uart0.r_buf[uart0.r_out]);printf(' ');//test
    uart0.r_out = (uart0.r_out+1) % Debug_r_buf_len;   
  }
}
uint16 crc_xmodem_update(uint16 crc,uint8 iDat)
{
  uint16 i;
  crc = crc^((uint16)iDat << 8);
  for(i=0; i<8; i++){
    if(crc & 0x8000){
      crc = (crc << 1)^0x1021; 
    }else{
      crc <<= 1; 
    }
  } 
  return crc;
}

//计算CRC16
uint16 calcrc(uint8 *ptr, uint8 count)
{
  uint16 crc = 0;
   
    while (count--)
    {
        crc = crc_xmodem_update(crc,*ptr++);
    }
    return crc;
}
/* 写一页FLASH  */
void write_one_page(void)
{ 
  
  STM32_Flash_Write_Page((lFlashAddress+FLASH_EEPROM_Start_Addr),ReceiveDataBuf,FLASH_ERASE_EN);

/*  uint16 j;
  for(j=0; j<PAGE_SIZE; j++){
    if(((j % 128) == 0) || (j % 128) == 1){
      uart0_puthex(ReceiveDataBuf[j]);
    }else if((j % 128) == 2){
      printf(' ');
    }
  }*/
}
/* 升级程序 */
void Cope_EEPROM_To_Flash(void)
{
  uint8 i,iCount_Temp;
//  uint16 j;
  
  iCount_Temp = lUpdata_Length/PAGE_SIZE+1;
  
  for(i=0; i<iCount_Temp; i++){
    STM32_Flash_Read_Page((FLASH_EEPROM_Start_Addr+(uint32)i*PAGE_SIZE), ReceiveDataBuf);
    
/*    for(j=0; j<PAGE_SIZE; j++){
      if(((j % 128) == 0) || (j % 128) == 1){
        uart0_puthex(ReceiveDataBuf[j]);
      }else if((j % 128) == 2){
        printf(' ');
      }
    }*/
    STM32_Flash_Write_Page((APP_AREA_ADDR+(uint32)i*PAGE_SIZE),ReceiveDataBuf,FLASH_ERASE_EN);   
  }
  
  iTemp_Buf[0] = 0xAA;
  iTemp_Buf[1] = 0x55;
  STM32_EEPROM_Write(EE_SYS_IAP_CMD,(uint8 *)iTemp_Buf,2,0);
	__set_FAULTMASK(1);      // 重启
	NVIC_SystemReset();// 
}

/* 退出启动程序，进入应用程序 */
void QuitBootLoad(void)
{
//  FunctionPtr Jump_To_Application;
//  u32 JumpAddress;
  
//  CLI();    // 关闭总中断
//  JumpAddress =  *(vu32*) (APP_AREA_ADDR + 4);          //应用代码起始地址
//  Jump_To_Application = (FunctionPtr)JumpAddress;	  //转换成函数指针
//  __set_MSP (*(vu32*) APP_AREA_ADDR);                   //初始化用户代码的堆栈指针 //__MSR_MSP(*(vu32*) APP_AREA_ADDR); 
//  Jump_To_Application();                               //跳转到用户代码
		printf("JMP to APP  \n");

		jump2app=(iapfun)*(vu32*)(APP_AREA_ADDR+4);		//用户代码区第二个字为程序开始地址(复位地址)		
		MSR_MSP(*(vu32*)APP_AREA_ADDR);					//初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址)
		jump2app();									//跳转到APP.

}





#define	MTD_Block_Num_Factory		1
#define	MTD_Block_Num_IDCard		63
#define	MTD_Block_Num_Password		64
#define	MTD_Block_Num_PrgInit		64
#define	MTD_Block_Num_PrgUpdate		64


#define	MTD_Block_Start_Factory		0
#define	MTD_Block_Start_IDCard		(MTD_Block_Start_Factory+MTD_Block_Num_Factory)
#define	MTD_Block_Start_Password	(MTD_Block_Start_IDCard+MTD_Block_Num_IDCard)
#define	MTD_Block_Start_PrgInit		(MTD_Block_Start_Password+MTD_Block_Num_Password)
#define	MTD_Block_Start_PrgUpdate	(MTD_Block_Start_PrgInit+MTD_Block_Num_PrgInit)

#define	MTD_Block_MAX				512


/**************************

	|*******|	0x00000
	|		|	Factory	
	|		|
	|*******|	0x01000
	|		|	IDCard	
	|		|		
	|*******|	0x40000
	|		|	Password
	|		|	
	|*******|	0x80000
	|		|	PrgInit
	|		|	
	|*******|	0xc0000
	|		|	PrgUpdate
	|		|	
	|*******|  0x100000	
	
	

****************////////


u8 ReadBuf[PAGE_SIZE];
uint8 Cope_SPIFlash_To_StmFlash(uint32 AddrMtd_Start)
{	
uint32 i;	
uint8 ret = 0;
uint8 UPDATAOK[2] = {0x00,0x00};	
	printf("Copy SPIFlash ROM  to StmFlash ROM start \n");
//---192k = 96*2K		
	for (i = 0; i < 96;i++)
	{	
		W25QXX_Read(ReadBuf,(AddrMtd_Start*4096+(uint32)i*PAGE_SIZE),PAGE_SIZE);
		printf("copy spiflash to stmflash:%d\n",i);
		ret = STM32_Flash_Write_Page((APP_AREA_ADDR+(uint32)i*PAGE_SIZE),ReadBuf,FLASH_ERASE_EN);
//		memset(ReadBuf,0,PAGE_SIZE);
//		STM32_Flash_Read_Page((APP_AREA_ADDR+(uint32)i*PAGE_SIZE),ReadBuf);
	}
	W25QXX_Write(UPDATAOK,(MTD_Block_Start_PrgUpdate*4096+0x40000-2),2);
	printf("Copy SPIFlash ROM  to StmFlash ROM end \n");
	return ret;
}


void Cope_StmFlash_To_SPIFlash(uint32 AddrMtd_Start)
{	
int i;	

//---192k = 96*2K	
	printf("Copy StmFlash ROM  to SPIFlash ROM start\n");	
	for (i = 0; i < 96;i++)
	{	
		STM32_Flash_Read_Page((APP_AREA_ADDR+(uint32)i*PAGE_SIZE),ReadBuf);
		W25QXX_Write(ReadBuf,(AddrMtd_Start*4096+(uint32)i*PAGE_SIZE),PAGE_SIZE);		
		printf("copy stmflash to spiflash:%d\n",i);
	}
	printf("Copy StmFlash ROM  to SPIFlash ROM end\n");	
}


void SPIFLASH_CheckRom_Status(void)
{
//	Cope_StmFlash_To_SPIFlash(MTD_Block_Start_PrgInit);	
	W25QXX_Read(ReadBuf,(MTD_Block_Start_PrgUpdate*4096+0x40000-2),2);
	if (((ReadBuf[0] == 0xff)&& (ReadBuf[1] == 0xff)) || ((ReadBuf[0] == 0x00)&& (ReadBuf[1] == 0x00)) )
	{
		QuitBootLoad();
	}
	else if ((ReadBuf[0] == 0x55)&& (ReadBuf[1] == 0xaa))
	{
		printf("JMP to Update  APP Start\n");
		Cope_SPIFlash_To_StmFlash(MTD_Block_Start_PrgUpdate);
		printf("JMP to Update  APP End\n");
		QuitBootLoad();	
	
	}	
 		
}	




/******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/
